package cn.itcast.backend3;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class DbComparator {

    public CompareResult compare(Db db1, Db db2) {
        CompareResult result = new CompareResult();
        result.setColumnDiffs(compareColumns(db1, db2));
        result.setTableDiffs(compareTables(db1, db2));
        return result;
    }

    private List<TableDiff> compareTables(Db db1, Db db2) {
        List<TableDiff> tableDiffs = new ArrayList<>();
        try (Connection conn1 = DriverManager.getConnection(db1.getUrl(), db1.getUsername(), db1.getPassword());
             Connection conn2 = DriverManager.getConnection(db2.getUrl(), db2.getUsername(), db2.getPassword())) {

            DatabaseMetaData meta1 = conn1.getMetaData();
            DatabaseMetaData meta2 = conn2.getMetaData();

            ResultSet tables1 = meta1.getTables(null, null, "%", new String[]{"TABLE"});
            ResultSet tables2 = meta2.getTables(null, null, "%", new String[]{"TABLE"});

            Map<String, Boolean> tableMap1 = new HashMap<>();
            Map<String, Boolean> tableMap2 = new HashMap<>();

            while (tables1.next()) {
                tableMap1.put(tables1.getString("TABLE_NAME"), true);
            }

            while (tables2.next()) {
                String tableName = tables2.getString("TABLE_NAME");
                tableMap2.put(tableName, true);

                if (tableMap1.containsKey(tableName)) {
                    tableMap1.remove(tableName);
                    tableMap2.remove(tableName);
                }
            }

            for (String tableName : tableMap1.keySet()) {
                tableDiffs.add(new TableDiff(tableName, 3));
            }

            for (String tableName : tableMap2.keySet()) {
                tableDiffs.add(new TableDiff(tableName, 4));
            }

            for (String tableName : tableMap1.keySet()) {
                if (tableMap2.containsKey(tableName)) {
                    // Compare columns here or later
                    tableDiffs.add(new TableDiff(tableName, 2));
                }
            }

        } catch (SQLException e) {
            e.printStackTrace();
        }
        return tableDiffs;
    }

    private List<ColumnDiff> compareColumns(Db db1, Db db2) {
        List<ColumnDiff> columnDiffs = new ArrayList<>();
        return columnDiffs;
    }

    // Main method for testing
    public static void main(String[] args) {
        Db db1 = new Db("com.mysql.jdbc.Driver", "jdbc:mysql://localhost:3306/zaixiansc?useUnicode=true&characterEncoding=utf8", "root", "root");
        Db db2 = new Db("com.mysql.jdbc.Driver", "jdbc:mysql://localhost:3306/xsxkglxt?useUnicode=true&characterEncoding=utf8", "root", "root");
//        Db db2 = new Db("com.mysql.jdbc.Driver", "jdbc:mysql://localhost:3306/zaixiansc?useUnicode=true&characterEncoding=utf8", "root", "root");

        DbComparator comparator = new DbComparator();
        CompareResult result = comparator.compare(db1, db2);

        System.out.println("Table Differences: " + result.getTableDiffs());
        System.out.println("Column Differences: " + result.getColumnDiffs());
    }
}

@Data
@AllArgsConstructor
@NoArgsConstructor
class Db {
    private String name;
    private String url;
    private String username;
    private String password;
}

@Data
@AllArgsConstructor
@NoArgsConstructor
class CompareResult {
    private List<ColumnDiff> columnDiffs;
    private List<TableDiff> tableDiffs;
}

@Data
@AllArgsConstructor
@NoArgsConstructor
class TableDiff {
    private String name;
    private int diff;
}

@Data
@AllArgsConstructor
@NoArgsConstructor
class ColumnDiff {
    private String table;
    private String name;
    private int diff;
}
